package pl.pelcra.cesar.spider.webcrawler.interfaces;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.apache.http.message.BasicNameValuePair;

import edu.uci.ics.crawler4j.crawler.Page;
import edu.uci.ics.crawler4j.parser.HtmlParseData;
import edu.uci.ics.crawler4j.url.WebURL;

/**
 * class that represent one object of task to process page on specified depth
 * 
 * @author margielewski
 * 
 */
public class WebTask {

	/**
	 * copy constructor of webTask
	 * 
	 * @param webTask
	 *            current webTask
	 * @return return new instance of WebTask
	 */
	public static WebTask newInstance(WebTask webTask) {
		if (webTask != null) {
			WebTask newWebTask = new WebTask();
			newWebTask.filterRules = FilterRules
					.newInstance(webTask.filterRules);
			newWebTask.iPageActions = webTask.iPageActions;
			newWebTask.nextWebTask = webTask.nextWebTask;
			newWebTask.parallelWebTask = webTask.parallelWebTask;
			return newWebTask;
		}
		return null;
	}

	private WebURL curURL = null;
	private FilterRules filterRules;
	private IPageActions iPageActions = null;
	private List<WebURL> listWebUrl;
	private HashMap<String, String> mapParametrs = null;
	private WebTask nextWebTask = null;

	private WebTask parallelWebTask = null;

	/**
	 * parameterless constructor
	 */
	public WebTask() {
		this.filterRules = new FilterRules();
		this.listWebUrl = new ArrayList<WebURL>();
	}

	/**
	 * constructor that initialize all objects and set next webTask
	 * 
	 * @param nextWebTask
	 *            next webTask
	 */
	public WebTask(WebTask nextWebTask) {
		this();
		this.nextWebTask = nextWebTask;
	}

	/**
	 * constructor that initialize all objects and set next webTask and next
	 * parallel webTask
	 * 
	 * @param nextWikiWebTask
	 *            next webTask
	 * @param parallelWikiWebTask
	 *            next parallel webTask
	 */
	public WebTask(WebTask nextWikiWebTask, WebTask parallelWikiWebTask) {
		this();
		this.nextWebTask = nextWikiWebTask;
		this.parallelWebTask = parallelWikiWebTask;
	}

	/**
	 * add new interface for current webTask
	 * 
	 * @param iPageActions
	 *            interface iPageActions
	 */
	public void addIPageActions(IPageActions iPageActions) {
		this.iPageActions = iPageActions;
	}

	/**
	 * add new parameter to filterRules
	 * 
	 * @param parameter
	 *            new object parameter
	 */
	public void addParametrToRules(Object parameter) {
		if (this.filterRules != null) {
			this.filterRules.addListParameter(parameter);
		}
	}

	/**
	 * add list of webUrl to listListWebUrls on this webTask
	 * 
	 * @param listWebURL
	 *            new list webUrl from this page
	 */
	public void addWebURL(List<WebURL> listWebURL) {
		for (WebURL url : listWebURL) {
			this.addWebURL(url);
		}
	}

	/**
	 * add new webUrl to listListWebUrls on this webTask
	 * 
	 * @param webURL
	 *            new webUrl from this page
	 */
	public void addWebURL(WebURL webURL) {
		if (!this.getListWebUrl().contains(webURL)) {
			this.getListWebUrl().add(webURL);
		}
	}

	/**
	 * invoke function afterProcessPage from IPageActions interface last action
	 * during processing page
	 * 
	 * @param webTask
	 *            actual webTask which is processed
	 * @param page
	 *            page object
	 * @param htmlParseData
	 *            page content as HtmlParseData object
	 */
	public void afterProcessPage(WebTask webTask, Page page,
			HtmlParseData htmlParseData) {
		if (this.iPageActions != null) {
			this.iPageActions.afterProcessPage(webTask, page, htmlParseData);
		}
	}

	/**
	 * invoke function beforeProcessPage from IPageActions interface first
	 * action after get page content
	 * 
	 * @param htmlParseData
	 *            page content as HtmlParseData object
	 */
	public void beforeProcessPage(HtmlParseData htmlParseData) {
		if (this.iPageActions != null) {
			this.iPageActions.beforeProcessPage(htmlParseData);
		}
	}

	/**
	 * invoke function filterUrl from IPageActions interface
	 * 
	 * @param url
	 *            current url
	 * @return return true if url is satisfies the conditions otherwise return
	 *         false
	 */
	public boolean filterUrl(WebURL url) {
		if (this.iPageActions != null) {
			return this.iPageActions.filterUrl(url, this);
		} else {
			return true;
		}
	}

	/**
	 * invoke function finishProcessWebTasks from IPageActions interface
	 */
	public void finishProcessWebTasks() {
		if (this.iPageActions != null) {
			this.iPageActions.finishProcessWebTasks(this);
		}
	}

	/**
	 * 
	 * @return return current webUrl
	 */
	public WebURL getCurWebURL() {
		return this.curURL;
	}

	/**
	 * invoke function getFilterParallelWebUrl from IPageActions interface
	 * 
	 * @return return next parallel webUrl
	 */
	public WebURL getFilterParallelWebUrl() {
		if (this.iPageActions != null) {
			return this.iPageActions.getFilterParallelWebUrl(this.filterRules,
					this.listWebUrl);
		}
		return null;
	}

	/**
	 * 
	 * @return return filter rules
	 */
	public FilterRules getFilterRules() {
		return this.filterRules;
	}

	/**
	 * invoke function getHttpRequestMethod from IPageActions interface
	 * 
	 * @return return http request method
	 */
	public HttpRequestMethod getHttpRequestMethod() {
		if (this.iPageActions != null) {
			return this.iPageActions.getHttpRequestMethod();
		}
		return HttpRequestMethod.GET;
	}

	/**
	 * 
	 * @return return list of webUrls for current page
	 */
	public List<WebURL> getListWebUrl() {
		return this.listWebUrl;
	}

	/**
	 * 
	 * @return return next webTask
	 */
	public WebTask getNextWebTask() {
		return this.nextWebTask;
	}

	/**
	 * 
	 * @return return parallel webTask
	 */
	public WebTask getParallelWebTask() {
		return this.parallelWebTask;
	}

	/**
	 * invoke function getParameterValuePairs from IPageActions interface
	 * 
	 * @return return list BasicNameValuePair
	 */
	public List<BasicNameValuePair> getParameterValuePairs() {
		if (this.iPageActions != null) {
			return this.iPageActions.getParameterValuePairs(this.mapParametrs);
		}
		return null;
	}

	/**
	 * invoke function isCookieRequired from IPageActions interface
	 * 
	 * @return return true if cookie is required otherwise false
	 */
	public boolean isCookieRequired() {
		if (this.iPageActions != null) {
			return this.iPageActions.isCookieRequired();
		}
		return false;
	}

	/**
	 * invoke function isNextParallelPage from IPageActions interface
	 * 
	 * @param currentParallelWebUrl
	 *            current parallel webUrl
	 * @param filterParallelWebUrl
	 *            rules to filter parallel webUrls
	 * @return return true if next parallel page exists otherwise false
	 */
	public boolean isNextParallelPage(WebURL currentParallelWebUrl,
			WebURL filterParallelWebUrl) {
		if (this.iPageActions != null) {
			return this.iPageActions.isNextParallelPage(this,
					currentParallelWebUrl, filterParallelWebUrl);
		}
		return false;
	}

	/**
	 * 
	 * @return return true if next webTask exists otherwise return false
	 */
	public boolean isNextWebTask() {
		return this.nextWebTask != null;
	}

	/**
	 * invoke function isParallelProcess from IPageActions interface
	 * 
	 * @return return true if page is processed in parallel process otherwise
	 *         return false
	 */
	public boolean isParallelProcess() {
		if (this.iPageActions != null) {
			return this.iPageActions.isParallelProcess();
		}
		return false;
	}

	/**
	 * do some actions with all filtered urls. invoke function processListURLs
	 * from IPageActions interface
	 */
	public void processListURLs() {
		if (this.iPageActions != null) {
			this.iPageActions.processListURLs(this);
		}
	}

	/**
	 * set current webUrl
	 * 
	 * @param curURL
	 *            current webUrl
	 */
	public void setCurWebURL(WebURL curURL) {
		this.curURL = curURL;
	}

	/**
	 * set list of parameters for filter urls
	 * 
	 * @param listParameter
	 */
	public void setListParametrRules(List<Object> listParameter) {
		if (this.filterRules != null) {
			this.filterRules.setListParameter(listParameter);
		}
	}

	/**
	 * set list of webUrls for current page
	 * 
	 * @param listWebURL
	 */
	public void setListWebUrl(List<WebURL> listWebURL) {
		this.listWebUrl = listWebURL;
	}

	/**
	 * set map key - value of parameters
	 * 
	 * @param mapParametrs
	 */
	public void setMapParametrs(HashMap<String, String> mapParametrs) {
		this.mapParametrs = mapParametrs;
	}

	/**
	 * set next webTask
	 * 
	 * @param nextWebTask
	 *            next webTask
	 */
	public void setNextWikiWebTask(WebTask nextWebTask) {
		this.nextWebTask = nextWebTask;
	}
}
